package com.irdstudio.apicenter.gateway.comm.pack;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.irdstudio.apicenter.gateway.comm.MaccsPacket;
import com.irdstudio.apicenter.gateway.comm.MaccsPacketUtil;
import com.irdstudio.apicenter.gateway.core.dm.AppChannelForward;
import com.irdstudio.apicenter.gateway.util.XmlToHashMapUtil;
import com.irdstudio.apicenter.gateway.util.date.CurrentDateUtil;
import com.irdstudio.apicenter.gateway.util.pub.KeyUtil;
import com.irdstudio.apicenter.gateway.web.MaccsTradeDefineVo;

/**
 * 晋商消费项目组对应的TCP协议下的XML组/解包处理
 * 
 * @author guangming.li
 * @version 1.0
 * @date 2015-10-13
 */
@Service(value = "JshXmlPackProcessor")
public class JshXmlPackProcessor extends AbstracePackProcessor {

	/* 文本日志记录对象(Logback对象) */
	private final static Logger logger = LoggerFactory
			.getLogger(JshXmlPackProcessor.class);

	@Override
	public MaccsPacket getReadPackage(AppChannelForward acf,
			MaccsTradeDefineVo tradeDefine, String result) {

		logger.info("返回信息(目标):" + result);
		MaccsPacket backPacket = null;

		// 1.将接收到的数据转换为Map对象并封装成MaccsPacket返回
		XmlMapper xmlMapper = new XmlMapper();
		// String backMsg =
		// "<?xml version=\"1.0\" encoding=\"utf-8\" ?><reponse>       <head>              <retFlag>0000</retFlag>              <retMsg>11111111</retMsg>       </head>       <body>              <applCde>111111111</applCde>       </body></reponse>";
		Map<String, Object> backXmlMap = null;
		try {
			// backXmlMap = xmlMapper.readValue(result, Map.class);
			backXmlMap = xml2HashMap(result);
			// backXmlMap = XmlToHashMapUtil.xml2map(result);

			// 2.判断返回的报文是否符合要求,晋商的报文中如果没有返回数据则没有body段
			if (backXmlMap.get("head") == null
					|| !(backXmlMap.get("head") instanceof HashMap<?, ?>)) {
				return MaccsPacketUtil.makeFailurePacket("收到的报文不符合格式要求!");
			}

			// 3.将接收到XML报文头信息转换为移动应用前端能识别的报文
			Map<String, Object> rspHead = (Map<String, Object>) backXmlMap
					.get("head");
			Map<String, Object> rspBody = null;
			if (backXmlMap.get("body") == null
					|| !(backXmlMap.get("body") instanceof HashMap<?, ?>)) {
				rspBody = new HashMap<String, Object>();
			} else {
				rspBody = (Map<String, Object>) backXmlMap.get("body");
			}
			if ("E0000".equals(rspHead.get("successCode"))) {
				rspBody.put("ec", MaccsPacketUtil.SUCCESS_FLAG);
			} else {
				rspBody.put("ec", rspHead.get("successCode"));
			}
			rspBody.put("em", rspHead.get("errorMessage"));

			// 4. 返回给前端响应的数据(报文头经过转换后成为报文体MAP对象中的一部分

			backPacket = new MaccsPacket(rspBody);

		} catch (Exception e) {
			backPacket = MaccsPacketUtil.makeFailurePacket(e.getMessage());
			e.printStackTrace();
		}

		return backPacket;
	}

	/**
	 * 组装成要发送的XML报文
	 */
	@Override
	public String getSendPackage(AppChannelForward acf,
			MaccsTradeDefineVo tradeDefine, MaccsPacket inUvo) {
		// 3.将要发送的内容组装成XML报文
		StringBuffer sendXmlMsg = new StringBuffer(
				"<?xml version=\"1.0\" encoding=\"").append(
				acf.getChannelCharset()).append("\" ?>");
		sendXmlMsg.append("<root>");
		// 3.1 根据渠道要求组合成报文体(后续应考虑改为配置)
		sendXmlMsg.append("<head>");
		sendXmlMsg.append("<tranCode>").append(tradeDefine.getTradeCode())
				.append("</tranCode>");
		sendXmlMsg.append("<applSeq>").append(KeyUtil.createUniqueKey())
				.append("</applSeq>");
		// sendXmlMsg.append("<sysFlag>").append(acf.getAppId())
		// .append("</sysFlag>");
		// sendXmlMsg.append("<tradeType>").append("11111111111")
		// .append("</tradeType>");
		sendXmlMsg.append("<tranDate>").append(CurrentDateUtil.getTodayDate())
				.append("</tranDate>");
		sendXmlMsg.append("<tranTime>")
				.append(CurrentDateUtil.getCurrentTime()).append("</tranTime>");
		sendXmlMsg.append("<chlGrp>").append("0001").append("</chlGrp>");
		sendXmlMsg.append("<bchCde>").append("900000").append("</bchCde>");
		sendXmlMsg.append("<version>").append("1.0").append("</version>");
		sendXmlMsg.append("</head>");
		// 3.2 遍历inUvo，组成要发送的XML的报文体
		sendXmlMsg.append("<body>");
		for (Iterator<?> iter = inUvo.getMap().keySet().iterator(); iter
				.hasNext();) {
			String f = (String) iter.next();
			sendXmlMsg.append("<").append(f).append(">");
			sendXmlMsg.append(inUvo.getValue(f));
			sendXmlMsg.append("</").append(f).append(">");
		}
		sendXmlMsg.append("</body>");
		sendXmlMsg.append("</root>");

		// 3.3 组成完整的XML报文(6位长度+报文)
		String msgLength = "000000" + sendXmlMsg.toString().getBytes().length;
		StringBuffer fullXmlMsg = new StringBuffer();
		fullXmlMsg.append(msgLength.substring(msgLength.length() - 6));
		fullXmlMsg.append(sendXmlMsg);

		// 打印要发送的报文内容到控制台
		logger.info("发送信息(目标):" + fullXmlMsg);

		return fullXmlMsg.toString();
	}

	/**
	 * 解析返回的xml报文为HashMap(针对晋商消费贷)
	 * 
	 * @param xmlStr
	 *            xml字符串
	 * @return HashMap
	 */
	public HashMap<String, Object> xml2HashMap(String xmlStr) {
		if (xmlStr == null || "".equals(xmlStr.trim())) {
			return null;
		}
		if (null != xmlStr && !"".equals(xmlStr)) {
			if (xmlStr.indexOf("<") != -1 && xmlStr.lastIndexOf(">") != -1
					&& xmlStr.lastIndexOf(">") > xmlStr.indexOf("<"))
				xmlStr = xmlStr.substring(xmlStr.indexOf("<"),
						xmlStr.lastIndexOf(">") + 1);
		}
		HashMap<String, Object> xmlHashMap = new HashMap<String, Object>();
		try {
			Document document = DocumentHelper.parseText(xmlStr);
			for (Iterator i = document.getRootElement().elementIterator(); i
					.hasNext();) {
				Element element = (Element) i.next();
				HashMap<String, Object> notHashMap = new HashMap<String, Object>();
				for (Iterator j = element.elementIterator(); j.hasNext();) {
					Element e = (Element) j.next();
					String elementName = e.getName().trim();
					if (elementName.equals("approvearray")
							|| elementName.equals("paybackarray")
							|| elementName.equals("coltarray")
							|| elementName.equals("listarray")) {// 如果是数组就用list接收
						List arrylist = new ArrayList();
						for (Iterator k = e.elementIterator(); k.hasNext();) {
							Element m = (Element) k.next();
							HashMap listHashMap = new HashMap();
							for (Iterator l = m.elementIterator(); l.hasNext();) {
								Element z = (Element) l.next();
								listHashMap.put(z.getName(), z.getText());
							}
							arrylist.add(listHashMap);
						}
						notHashMap.put(e.getName(), arrylist);
					} else if (elementName.equals("termarray")) {// termarray数组中也有数组单独处理
						List termarrayList = new ArrayList();// 用来装termarray节点下的term节点
						for (Iterator termElementList = e.elementIterator(); termElementList
								.hasNext();) {// 开始遍历termarray节点下的term节点
							Element oneOfTermElement = (Element) termElementList
									.next();// 得到每一个term节点
							HashMap termChildrenHashMap = new HashMap();// 用来装term节点下的子节点
							for (Iterator termChildren = oneOfTermElement
									.elementIterator(); termChildren.hasNext();) {
								Element termChildrenElement = (Element) termChildren
										.next();// 得到termarray节点下的子节点:term
								if (termChildrenElement.getName().trim()
										.equals("mtdarray")) {// term子节点中有一个叫mtdarray节点的他也是一个数组
									List mtdArrylist = new ArrayList();// 用来装mtdarray下的mtd节点

									for (Iterator mtd = termChildrenElement
											.elementIterator(); mtd.hasNext();) {// 遍历mtdarray节点
										Element oneOfmtdElement = (Element) mtd
												.next();// 得到mtdarray节点下的某一个mtd节点
										HashMap mtdListHashMap = new HashMap();// mtd节点下的子节点
										for (Iterator mtdChildrenElement = oneOfmtdElement
												.elementIterator(); mtdChildrenElement
												.hasNext();) {// 遍历mtd节点
											Element mtdLastElement = (Element) mtdChildrenElement
													.next();// 得到mtd节点下每一个子节点
											mtdListHashMap.put(
													mtdLastElement.getName(),
													mtdLastElement.getText());
										}
										mtdArrylist.add(mtdListHashMap);
									}
									termChildrenHashMap.put(
											termChildrenElement.getName(),
											mtdArrylist);
								} else {
									termChildrenHashMap.put(
											termChildrenElement.getName(),
											termChildrenElement.getText());
								}
							}
							termarrayList.add(termChildrenHashMap);
						}
						notHashMap.put(e.getName(), termarrayList);
					} else {
						notHashMap.put(e.getName(), e.getText());
					}
				}
				xmlHashMap.put(element.getName(), notHashMap);
			}
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return xmlHashMap;
	}

}
